﻿#include "service_register_zookeeper.hh"
#include "../../util/string_util.hh"
#include "../zookeeper/zookeeper_client.hh"
#include <vector>

namespace kratos {
namespace service {

ServiceRegisterZookeeper::ServiceRegisterZookeeper() {}

ServiceRegisterZookeeper::~ServiceRegisterZookeeper() {}

bool ServiceRegisterZookeeper::start(const std::string &servers, int timeout) {
  if (zoo_ptr_) {
    if (zoo_ptr_->is_connected()) {
      return true;
    }
  }
  if (servers.empty()) {
    return false;
  }
  if (timeout <= 0) {
    timeout = 1000;
  }
  zoo_ptr_ = make_unique_pool_ptr<ZookeeperClient>();
  return zoo_ptr_->connect(servers, timeout);
}

bool ServiceRegisterZookeeper::stop() {
  if (!zoo_ptr_) {
    return false;
  }
  auto result = zoo_ptr_->disconnect();
  // 释放, 其他调用函数都将失效
  zoo_ptr_.reset();
  return result;
}

void ServiceRegisterZookeeper::update(std::time_t tick) {
  if (!zoo_ptr_) {
    return;
  }
  if (!tick) {
    last_tick_ = tick;
  }
  if (tick - last_tick_ >= CHECK_INTERVAL) {
    if (!zoo_ptr_->is_connected()) {
      if (zoo_ptr_->reconnect()) {
        for (const auto &[k, v] : already_register_map_) {
          register_service(k, v);
        }
      }
    }
    last_tick_ = tick;
  }
}

bool ServiceRegisterZookeeper::register_service(const std::string &name,
                                                const std::string &host) {
  if (!zoo_ptr_) {
    return false;
  }
  if (name.empty() || host.empty()) {
    return false;
  }
  std::string real_name;
  if (name[0] != '/') {
    real_name = "/" + name;
  } else {
    real_name = name;
  }
  if (!zoo_ptr_->exists(real_name)) {
    std::vector<std::string> result;
    util::split(name, "/", result);
    std::string full_path("/");
    for (const auto &path : result) {
      full_path += path;
      if (!zoo_ptr_->exists(full_path)) {
        zoo_ptr_->set_path(full_path, "");
      }
      full_path += "/";
    }
  }
  if (zoo_ptr_->set(real_name + "/" + host, "")) {
    already_register_map_.emplace(name, host);
    return true;
  } else {
    return false;
  }
}

bool ServiceRegisterZookeeper::unregister_service(const std::string &name,
                                                  const std::string &host) {
  if (!zoo_ptr_) {
    return false;
  }
  if (name.empty() || host.empty()) {
    return false;
  }
  std::string real_name;
  if (name[0] != '/') {
    real_name = "/" + name;
  } else {
    real_name = name;
  }
  if (zoo_ptr_->remove(real_name + "/" + host)) {
    already_register_map_.erase(name);
    return true;
  } else {
    return false;
  }
}

} // namespace service
} // namespace kratos
